﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace ElectronicCommerce.Framework.Web.UI.GeneratedImage.ImageTransform
{
    public class ImageResizeTransform : ImageTransform
    {
        private int _width, _height;

        public ImageResizeTransform()
        {
            InterpolationMode = InterpolationMode.HighQualityBicubic;
            Mode = ImageResizeMode.Fit;
        }

        /// <summary>
        /// Sets the resize mode. The default value is Fit.
        /// </summary>
        [DefaultValue(ImageResizeMode.Fit)]
        [Category("Behavior")]
        public ImageResizeMode Mode { get; set; }

        /// <summary>
        /// Sets the maximum width of the resulting image
        /// </summary>
        [DefaultValue(0)]
        [Category("Behavior")]
        public int Width
        {
            get
            {
                return _width;
            }
            set
            {
                CheckValue(value);
                _width = value;
            }
        }

        /// <summary>
        /// Sets the maximum height of the resulting image
        /// </summary>
        [DefaultValue(0)]
        [Category("Behavior")]
        public int Height
        {
            get
            {
                return _height;
            }
            set
            {
                CheckValue(value);
                _height = value;
            }
        }

        /// <summary>
        /// Sets the interpolation mode used for resizing images. The default is HighQualityBicubic.
        /// </summary>
        [DefaultValue(InterpolationMode.HighQualityBicubic)]
        [Category("Behavior")]
        public InterpolationMode InterpolationMode { get; set; }

        private static void CheckValue(int value)
        {
            if (value < 0)
            {
                throw new ArgumentOutOfRangeException("value");
            }
        }

        /// <summary>
        /// 执行图片转换
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        public override Image ProcessImage(Image img)
        {
            //int scaledHeight = (int)(img.Height * ((float)this.Width / (float)img.Width));
            //int scaledWidth = (int)(img.Width * ((float)this.Height / (float)img.Height));
            Size orgSize = new Size();
            orgSize.Height = this.Height;
            orgSize.Width = this.Width;
            Size newSize = ImageSizeHelper.Resize(img, orgSize);

            switch (Mode)
            {
                case ImageResizeMode.Fit:
                    return FitImage(img, newSize.Height, newSize.Width);
                case ImageResizeMode.Crop:
                    return CropImage(img, newSize.Height, newSize.Width);
                default:
                    Debug.Fail("Should not reach this");
                    return null;
            }
        }

        /// <summary>
        /// 按比例进行图片缩放
        /// </summary>
        /// <param name="img"></param>
        /// <param name="scaled_height"></param>
        /// <param name="scaled_width"></param>
        /// <returns></returns>
        private Image FitImage(Image img, int scaled_height, int scaled_width)
        {
            Bitmap newImage = new Bitmap(this.Width, this.Height);
            newImage.SetResolution(img.HorizontalResolution, img.HorizontalResolution);
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                SetupGraphics(graphics);
                Rectangle rectangle = new Rectangle((this.Width - scaled_width) / 2, (this.Height - scaled_height) / 2, scaled_width, scaled_height);
                graphics.DrawImage(img, rectangle);
                return newImage;
            }
        }

        /// <summary>
        /// 裁剪图片
        /// </summary>
        /// <param name="img"></param>
        /// <param name="scaledHeight"></param>
        /// <param name="scaledWidth"></param>
        /// <returns></returns>
        private Image CropImage(Image img, int scaledHeight, int scaledWidth)
        {
            int resizeWidth = 0;
            int resizeHeight = 0;
            if (((float)this.Width / (float)img.Width > this.Height / (float)img.Height))
            {
                resizeWidth = this.Width;
                resizeHeight = scaledHeight;
            }
            else
            {
                resizeWidth = scaledWidth;
                resizeHeight = this.Height;
            }

            Bitmap newImage = new Bitmap(this.Width, this.Height);
            newImage.SetResolution(img.HorizontalResolution, img.HorizontalResolution);
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                SetupGraphics(graphics);
                Rectangle rectangle = new Rectangle((this.Width - resizeWidth) / 2, (this.Height - resizeHeight) / 2, resizeWidth, resizeHeight);
                graphics.DrawImage(img, rectangle);
                return newImage;
            }
        }

        /// <summary>
        /// 设置画板属性
        /// </summary>
        /// <param name="graphics"></param>
        private void SetupGraphics(Graphics graphics)
        {
            graphics.CompositingMode = CompositingMode.SourceCopy;
            graphics.CompositingQuality = CompositingQuality.HighSpeed;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.InterpolationMode = InterpolationMode;
            graphics.Clear(Color.White);
        }

        /// <summary>
        /// 图片标志字符串, 用于生成缓存图片用
        /// </summary>
        [Browsable(false)]
        public override string UniqueString
        {
            get
            {
                return base.UniqueString + Width + InterpolationMode.ToString() + Height + Mode.ToString();
            }
        }

        public override string ToString()
        {
            return "ImageResizeTransform";
        }

        public Image BuildImage(string path, Size size)
        {
            using (Image img = Image.FromFile(path))
            {
                Size newSize = ImageSizeHelper.Resize(img, size);
                this.Width = size.Width;
                this.Height = size.Height;
                return FitImage(img, newSize.Height, newSize.Width);
            }
        }
    }
}
